package com.milling.web.utils;

import com.alibaba.fastjson.JSONObject;
import com.milling.business.BusinessConstants;
import com.milling.business.GlobalVariable;
import com.milling.business.domain.WmsBoxInfo;
import com.milling.business.domain.WmsNeedleSortting;
import com.milling.business.service.IWmsBoxInfoService;
import com.milling.business.service.IWmsNeedleSorttingService;
import com.milling.business.service.SuspendTaskManager;
import com.milling.common.core.redis.RedisCache;
import com.milling.common.utils.SocketUtils;
import com.milling.common.utils.StringUtils;
import com.milling.common.utils.modbus.ModbusMasterPoolFactory;
import com.milling.common.utils.modbus.ModbusServiceFactory;
import com.milling.common.utils.modbus.ModbusTcpService;
import com.milling.common.utils.modbus.ModbusTcpServiceImpl;
import com.milling.common.utils.scanner.SocketListener;
import com.milling.web.SpringContextHolder;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import org.apache.commons.pool2.ObjectPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Configuration
@ConditionalOnProperty(
        name = "mac.type",
        havingValue = "9",
        matchIfMissing = false // 当配置缺失时不加载
)
@Component
public class SortingScanner implements SocketListener.MessageCallback {
    private static final Logger logger = LoggerFactory.getLogger(SortingScanner.class);

    @Value("${sorting.scanner.ip}")
    private String sortingScannerIp;

    @Value("${sorting.scanner.port}")
    private int sortingScannerPort;

/*
    private final String host = "192.168.237.178"; // 从配置文件或命令行参数中读取

    private final int port = 502; // 从配置文件或命令行参数中读取

    private final int poolSize = 100; // 从配置文件或命令行参数中读取

    private int slaveId = 1;
*/

    /*@Value("${modbus.sorting.host}")
    private String host;// = "192.168.237.178"; // 从配置文件或命令行参数中读取

    @Value("${modbus.sorting.port}")
    private int port;// = 502; // 从配置文件或命令行参数中读取

    @Value("${modbus.sorting.poolSize}")
    private int poolSize;// = 100; // 从配置文件或命令行参数中读取

    @Value("${modbus.sorting.slaveId}")
    private int slaveId;// = 1;*/

    @Autowired
    private SuspendTaskManager suspendTaskManager;

    //    @Autowired
//    private ModbusUtil modbusUtil;
    private SocketUtils socketUtils; // 声明为成员变量

    // 从参数中读取IP、端口、slaveId和连接池大小
    @Value("${modbus.sorting.host:192.168.237.178}")
    private String host; // 从配置文件或命令行参数中读取

    @Value("${modbus.sorting.port:502}")
    private int port; // 从配置文件或命令行参数中读取

    @Value("${modbus.sorting.poolSize:5}")
    private int poolSize; // 从配置文件或命令行参数中读取

    @Value("${modbus.sorting.slaveId:1}")
    private int slaveId;

    // 获取Modbus服务实例
    private ModbusTcpService modbusTcpService;
    @Autowired
    private RedisCache redisCache;

    @PostConstruct
    public void init() {
        // 初始化 Modbus 服务
        modbusTcpService = ModbusServiceFactory.getModbusService(host, port, poolSize);
        logger.info("SortingScanner Modbus服务初始化完成 - {}:{}", host, port);

        // 初始化扫码器连接
        // 注意：SortingScanner 使用按需连接方式，不需要持久连接
    }

    @Autowired
    public SortingScanner(@Value("${sorting.scanner.ip}") String sortingScannerIp, @Value("${sorting.scanner.port}") int sortingScannerPort) {
        this.sortingScannerIp = sortingScannerIp;
        this.sortingScannerPort = sortingScannerPort;
        this.socketUtils = new SocketUtils(sortingScannerIp, sortingScannerPort); // 初始化
    }

    @Override
    public void onMessageReceived(String message) {
        // 创建连接池

//        logger.error("[分拣机扫码结果] " + message);
//        if("NoRead".equals(message)){
        if(message.contains("NoRead")){
            // 修复无限重试问题：添加扫码次数限制
            if(GlobalVariable.maxScanTimes <= 20) {
                GlobalVariable.maxScanTimes = GlobalVariable.maxScanTimes + 1;
                try {
                    //扫码 - 使用try-with-resources确保资源正确释放
                    try (SocketUtils tempSocketUtils = new SocketUtils(sortingScannerIp, sortingScannerPort)) {
                        tempSocketUtils.sendMessage("start");
                        Thread.sleep(50);
                    }
                } catch (Exception e) {
                    logger.error("[PLC]扫码失败", e);
                    logger.error("SortingScanner sendMessage Fail, boxId is: " + (getIntCache(GlobalVariable.SORTING_BOX_ID) + 1));
                    try {
                        modbusTcpService.writeHoldingRegister(slaveId, 5000, 1000);
                    } catch (ModbusTransportException ex) {
                        logger.error("[PLC]扫码失败，给5000地址写1000失败", ex);
                    } catch (Exception exx) {
                        logger.error("其他异常", exx);
                    }
                }
            } else {
                // 超过最大重试次数，重置计数器并记录错误
                GlobalVariable.maxScanTimes = 0;
                logger.error("分拣机扫码失败次数超过限制，已重置扫码计数器");
                // 可以在这里添加报警逻辑
            }
        } else {
            // 扫码成功，重置扫码次数
            synchronized(this) {
                GlobalVariable.maxScanTimes = 0;
            }
            logger.info("扫码结果 " + message);

            try {
                modbusTcpService.writeHoldingRegister(slaveId,5000, 0);//扫码成功，清空扫码信号
                logger.info("[PLC]扫码成功，给5000地址清0成功");
            } catch (ModbusTransportException ex) {
                ex.printStackTrace();
                logger.info("[PLC]扫码失败，给5000地址清0失败");
            } catch (Exception ex) {
                ex.printStackTrace();
                logger.info("[PLC]扫码成功，给5000地址清0失败");
            }

// 2. 遍历数组进行比较
            // 获取整个数组
            // 获取整个数组
//            List<String> sortingBoxList = redisCache.getCacheList(GlobalVariable.SORTING_BOX_CODE_ARRAY);
            List<String> sortingBoxList = (List<String>)redisCache.getCacheObject(GlobalVariable.SORTING_BOX_CODE_ARRAY);

            for (String code : sortingBoxList) {
                // 3. 防止数组元素为空导致NPE
                logger.info("清单中的盒子码： " + code);
            }

//            for (String code : GlobalVariable.SORTING_BOX_CODE_ARRAY) {
            for (String code : sortingBoxList) {
                // 3. 防止数组元素为空导致NPE
                if (code != null && code.equals(message)) {
                    // 4. 找到匹配项立即返回
                    logger.info("此针盒已经处理，继续...");
                    return;
                }
            }

            //判断message是否可以分拣(未分拣状态)
/*
//          查库，可以分拣则往下执行；已经分拣完的提示换针盒；不可以分拣则提示换针盒
            if(已分拣 || 无效二维码) {
                推送消息，前端展示二次确认窗，等待操作员现场确认
            } else {
                流程继续
            }
*/
            int boxId = 0;
            try {
//                GlobalVariable.SORTING_BOX_ID = modbusTcpService.readHoldingRegister(slaveId,3521);
                boxId = modbusTcpService.readHoldingRegister(slaveId,3521);
                redisCache.setCacheObject(GlobalVariable.SORTING_BOX_ID, boxId);
            } catch (ModbusTransportException ex) {
                ex.printStackTrace();
            } catch (Exception ex) {
                ex.printStackTrace();
            }

            //当前分拣的是第几盒
/*
            GlobalVariable.SORTING_BOX_CODE = message;
            GlobalVariable.SORTING_BOX_CODEARRAY[GlobalVariable.SORTING_BOX_ID - 1] = GlobalVariable.SORTING_BOX_CODE;
            logger.info("[PC]分拣托盘第：" + GlobalVariable.SORTING_BOX_ID + "盒针，二维码为：" + GlobalVariable.SORTING_BOX_CODE);
*/

            logger.info("[PC]分拣托盘第：" + boxId + "盒针，二维码为：" + message);

            // 验证boxId有效性，防止数组越界
            if (boxId < 1 || boxId > sortingBoxList.size()) {
                logger.error("SortingScanner: 无效的boxId: {}，数组大小: {}，请确认系统执行了PC端初始化", boxId, sortingBoxList.size());
                return;
            }

            redisCache.setCacheObject(GlobalVariable.SORTING_BOX_CODE, message);

            // 安全修改指定位置
            try {
                sortingBoxList.set(boxId - 1, message);
                // 写回Redis
//                redisCache.setCacheList(GlobalVariable.SORTING_BOX_CODE_ARRAY, sortingBoxList);
                redisCache.setCacheObject(GlobalVariable.SORTING_BOX_CODE_ARRAY, sortingBoxList);
                logger.info("成功更新分拣托盘第{}位二维码: {}", boxId, message);
            } catch (IndexOutOfBoundsException e) {
                logger.error("SortingScanner: 数组越界异常 - boxId: {}, 数组大小: {}", boxId, sortingBoxList.size(), e);
                return;
            }

            IWmsNeedleSorttingService wmsNeedleSorttingService = SpringContextHolder.getBean(IWmsNeedleSorttingService.class);
            wmsNeedleSorttingService.fixSorttingNeedleBox();

        }
    }

    @Override
    public void onConnectionClosed() {
        System.out.println("[INFO] SortingScanner Connection closed by server");
    }

    @Override
    public void onError(String errorMsg) {
        System.err.println("[ERROR] " + errorMsg);
    }

    private int getIntCache(String key) {
        return redisCache.getCacheObject(key) == null ? 0 : (int) redisCache.getCacheObject(key);
    }

    private String getStringCache(String key) {
        return redisCache.getCacheObject(key) == null ? "" : (String) redisCache.getCacheObject(key);
    }

}
